home *** CD-ROM | disk | FTP | other *** search
/ MacGames Sampler / PHT MacGames Bundle.iso / MacSource Folder / Samples from the CD / C and C++ / Gnuplot 3.5 for Macintosh / SOURCES 3.5 / readline.c < prev    next >
Text File  |  1993-11-12  |  22KB  |  961 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: readline.c%v 3.50.1.9 1993/08/05 05:38:59 woo Exp $";
  3. #endif
  4.  
  5.  
  6. /* GNUPLOT - readline.c */
  7. /*
  8.  * Copyright (C) 1986 - 1993   Thomas Williams, Colin Kelley
  9.  *
  10.  * Permission to use, copy, and distribute this software and its
  11.  * documentation for any purpose with or without fee is hereby granted, 
  12.  * provided that the above copyright notice appear in all copies and 
  13.  * that both that copyright notice and this permission notice appear 
  14.  * in supporting documentation.
  15.  *
  16.  * Permission to modify the software is granted, but not the right to
  17.  * distribute the modified code.  Modifications are to be distributed 
  18.  * as patches to released version.
  19.  *  
  20.  * This software is provided "as is" without express or implied warranty.
  21.  * 
  22.  *
  23.  * AUTHORS
  24.  *
  25.  *   Original Software:
  26.  *     Tom Tkacik
  27.  *
  28.  *   Msdos port and some enhancements:
  29.  *     Gershon Elber and many others.
  30.  * 
  31.  * There is a mailing list for gnuplot users. Note, however, that the
  32.  * newsgroup 
  33.  *    comp.graphics.gnuplot 
  34.  * is identical to the mailing list (they
  35.  * both carry the same set of messages). We prefer that you read the
  36.  * messages through that newsgroup, to subscribing to the mailing list.
  37.  * (If you can read that newsgroup, and are already on the mailing list,
  38.  * please send a message info-gnuplot-request@dartmouth.edu, asking to be
  39.  * removed from the mailing list.)
  40.  *
  41.  * The address for mailing to list members is
  42.  *       info-gnuplot@dartmouth.edu
  43.  * and for mailing administrative requests is 
  44.  *       info-gnuplot-request@dartmouth.edu
  45.  * The mailing list for bug reports is 
  46.  *       bug-gnuplot@dartmouth.edu
  47.  * The list of those interested in beta-test versions is
  48.  *       info-gnuplot-beta@dartmouth.edu
  49.  */
  50. #ifdef THINK_C
  51. #include "plot.h"
  52. #include "tout_protos.h"
  53. #endif
  54.  
  55. #ifdef READLINE
  56. #ifdef ATARI
  57. #include "plot.h"
  58. #endif
  59. #ifdef _WINDOWS
  60. #define _Windows
  61. #endif
  62.  
  63. /* a small portable version of GNU's readline */
  64. /* this is not the BASH or GNU EMACS version of READLINE due to Copyleft 
  65.     restrictions */
  66. /* do not need any terminal capabilities except backspace, */
  67. /* and space overwrites a character */
  68.  
  69. /* NANO-EMACS line editing facility */
  70. /* printable characters print as themselves (insert not overwrite) */
  71. /* ^A moves to the beginning of the line */
  72. /* ^B moves back a single character */
  73. /* ^E moves to the end of the line */
  74. /* ^F moves forward a single character */
  75. /* ^K kills from current position to the end of line */
  76. /* ^P moves back through history */
  77. /* ^N moves forward through history */
  78. /* ^H and DEL delete the previous character */
  79. /* ^D deletes the current character, or EOF if line is empty */
  80. /* ^L/^R redraw line in case it gets trashed */
  81. /* ^U kills the entire line */
  82. /* ^W kills last word */
  83. /* LF and CR return the entire line regardless of the cursor postition */
  84. /* EOF with an empty line returns (char *)NULL */
  85.  
  86. /* all other characters are ignored */
  87.  
  88. #include <stdio.h>
  89. #include <ctype.h>
  90. #include <signal.h>
  91.  
  92. #if !defined(MSDOS) && !defined(ATARI) && !defined(_Windows) && !defined(DOS386)
  93.  
  94. /*
  95.  * Set up structures using the proper include file
  96.  */
  97. #if defined(_IBMR2) || defined(alliant)
  98. #define SGTTY
  99. #endif
  100.  
  101. /*  submitted by Francois.Dagorn@cicb.fr */
  102. #ifdef SGTTY
  103. #include <sgtty.h>
  104. static struct sgttyb orig_termio, rl_termio;
  105. /* define terminal control characters */
  106. static struct tchars s_tchars;
  107. #define VERASE    0
  108. #define VEOF      1
  109. #define VKILL     2
  110. #ifdef TIOCGLTC         /* available only with the 'new' line discipline */
  111. static struct ltchars s_ltchars;
  112. #define VWERASE   3
  113. #define VREPRINT  4
  114. #define VSUSP     5
  115. #endif /* TIOCGLTC */
  116. #define NCCS      6
  117.  
  118. #else /* SGTTY */
  119.  
  120. /* SIGTSTP defines job control */
  121. /* if there is job control then we need termios.h instead of termio.h */
  122. /* (Are there any systems with job control that use termio.h?  I hope not.) */
  123. #ifdef SIGTSTP
  124. #define TERMIOS
  125. #include <termios.h>
  126. /* Added by Robert Eckardt, RobertE@beta.TP2.Ruhr-Uni-Bochum.de */
  127. #ifdef ISC22
  128. #ifndef ONOCR            /* taken from sys/termio.h */
  129. #define ONOCR 0000020    /* true at least for ISC 2.2 */
  130. #endif 
  131. #ifndef IUCLC
  132. #define IUCLC 0001000
  133. #endif
  134. #endif /* ISC22 */
  135.  
  136. static struct termios orig_termio, rl_termio;
  137. #else
  138. #include <termio.h>
  139. static struct termio orig_termio, rl_termio;
  140. /* termio defines NCC instead of NCCS */
  141. #define NCCS    NCC
  142. #endif /* SIGTSTP */
  143. #endif /* SGTTY */
  144.  
  145. /* ULTRIX defines VRPRNT instead of VREPRINT */
  146. #ifdef VRPRNT
  147. #define VREPRINT VRPRNT
  148. #endif
  149.  
  150. /* define characters to use with our input character handler */
  151. static char term_chars[NCCS];
  152.  
  153. static int term_set = 0;    /* =1 if rl_termio set */
  154.  
  155. #define special_getc() ansi_getc()
  156. static char ansi_getc();
  157.  
  158. #else /* !MSDOS && !ATARI && !_Windows */
  159.  
  160. #ifdef _Windows
  161. #include <windows.h>
  162. #include "win/wtext.h"
  163. #include "win/wgnuplib.h"
  164. extern TW textwin;
  165. #define TEXTUSER 0xf1
  166. #define TEXTGNUPLOT 0xf0
  167. #define special_getc() msdos_getch()
  168. static char msdos_getch();
  169. #endif
  170.  
  171. #if defined(MSDOS) || defined(DOS386)
  172. /* MSDOS specific stuff */
  173. #ifdef DJGPP
  174. #include <pc.h>
  175. #endif
  176. #ifdef __EMX__
  177. #include <conio.h>
  178. #endif
  179. #define special_getc() msdos_getch()
  180. static char msdos_getch();
  181. #endif /* MSDOS */
  182.  
  183. #ifdef ATARI
  184. #include <stdlib.h>
  185. #ifdef __PUREC__
  186. #include <tos.h>
  187. #else
  188. #include <osbind.h>
  189. #endif
  190. #define special_getc() tos_getch()
  191. static char tos_getch();
  192. #endif
  193.  
  194. #endif /* !MSDOS && !ATARI && !_Windows */
  195.  
  196. #if !defined(ATARI)
  197. /* is it <string.h> or <strings.h>?   just declare what we need */
  198. extern int      strlen();
  199. extern char *strcpy();
  200. #endif
  201. extern char *alloc();    /* we'll use the safe malloc from misc.c */
  202.  
  203. #define MAXBUF    1024
  204. #define BACKSPACE 0x08    /* ^H */
  205. #define SPACE    ' '
  206.  
  207. struct hist {
  208.     char *line;
  209.     struct hist *prev;
  210.     struct hist *next;
  211. };
  212.  
  213. static struct hist *history = NULL;  /* no history yet */
  214. static struct hist *cur_entry = NULL;
  215.  
  216. static char cur_line[MAXBUF];  /* current contents of the line */
  217. static int cur_pos = 0;    /* current position of the cursor */
  218. static int max_pos = 0;    /* maximum character position */
  219.  
  220.  
  221. void add_history();
  222. static void fix_line();
  223. static void redraw_line();
  224. static void clear_line();
  225. static void clear_eoline();
  226. static void copy_line();
  227. static void set_termio();
  228. static void reset_termio();
  229.  
  230. /* user_putc and user_puts should be used in the place of
  231.  * fputc(ch,stderr) and fputs(str,stderr) for all output
  232.  * of user typed characters.  This allows MS-Windows to 
  233.  * display user input in a different color. */
  234. int
  235. user_putc(ch)
  236. int ch;
  237. {
  238.     int rv;
  239. #ifdef _Windows
  240.     TextAttr(&textwin,TEXTUSER);
  241. #endif
  242.     rv = fputc(ch, stderr);
  243. #ifdef _Windows
  244.     TextAttr(&textwin,TEXTGNUPLOT);
  245. #endif
  246.     return rv;
  247. }
  248.  
  249. int
  250. user_puts(str)
  251. char *str;
  252. {
  253.     int rv;
  254. #ifdef _Windows
  255.     TextAttr(&textwin,TEXTUSER);
  256. #endif
  257.     rv = fputs(str, stderr);
  258. #ifdef _Windows
  259.     TextAttr(&textwin,TEXTGNUPLOT);
  260. #endif
  261.     return rv;
  262. }
  263.  
  264. /* This function provides a centralized non-destructive backspace capability */
  265. /* M. Castro */
  266.  
  267. backspace()
  268. {
  269.     user_putc(BACKSPACE);
  270. }
  271.     
  272. char *
  273. readline(prompt)
  274. char *prompt;
  275. {
  276.  
  277.     unsigned char cur_char;
  278.     char *new_line;
  279.     /* unsigned char *new_line; */
  280.  
  281.     /* set the termio so we can do our own input processing */
  282.     set_termio();
  283.  
  284.     /* print the prompt */
  285.     fputs(prompt, stderr);
  286.     cur_line[0] = '\0';
  287.     cur_pos = 0;
  288.     max_pos = 0;
  289.     cur_entry = NULL;
  290.  
  291.     /* get characters */
  292.     for(;;) {
  293.         cur_char = special_getc();
  294. #ifdef OS2
  295.  /* for emx: remap scan codes for cursor keys */
  296.                 if( cur_char == 0 ) {
  297.                     cur_char = getc(stdin);
  298.                     switch( cur_char){
  299.                         case 75:  /* left, map to ^B */
  300.                             cur_char=2;
  301.                             break ;
  302.                         case 77:  /* right, map to ^F */
  303.                             cur_char=6;
  304.                             break ;
  305.                         case 115: /* ctrl left */
  306.                         case 71:  /* home, map to ^A */
  307.                             cur_char=1;
  308.                             break ;
  309.                         case 116: /* ctrl right */
  310.                         case 79:  /* end, map to ^E */
  311.                             cur_char=5;
  312.                             break ;
  313.                         case 72:  /* up, map to ^P */
  314.                             cur_char=16;
  315.                             break ;
  316.                         case 80:  /* down, map to ^N */
  317.                             cur_char=14;
  318.                             break ;
  319.                         case 83:  /* delete, map to ^D */
  320.                             cur_char=4;
  321.                             break ;
  322.                         default:  /* ignore */
  323.                             cur_char=0;
  324.                             continue ;
  325.                             }
  326.                         }
  327. #endif  /*OS2*/
  328.         if((isprint(cur_char) 
  329. #if defined(ATARI) || defined(_Windows) || defined(MSDOS) || defined(DOS386)
  330.    /* this should be used for all 8bit ASCII machines, I guess */
  331.                     || ((unsigned char)cur_char > 0x7f)
  332. #endif
  333.                                )&& max_pos<MAXBUF-1) {
  334.             int i;
  335.             for(i=max_pos; i>cur_pos; i--) {
  336.                 cur_line[i] = cur_line[i-1];
  337.             }
  338.             user_putc(cur_char);
  339.             cur_line[cur_pos] = cur_char;
  340.             cur_pos += 1;
  341.             max_pos += 1;
  342.             if (cur_pos < max_pos)
  343.                 fix_line();
  344.             cur_line[max_pos] = '\0';
  345.  
  346.         /* else interpret unix terminal driver characters */
  347. #ifdef VERASE
  348.         } else if(cur_char == term_chars[VERASE] ){  /* DEL? */
  349.             if(cur_pos > 0) {
  350.                 int i;
  351.                 cur_pos -= 1;
  352.                 backspace();
  353.                 for(i=cur_pos; i<max_pos; i++)
  354.                     cur_line[i] = cur_line[i+1];
  355.                 max_pos -= 1;
  356.                 fix_line();
  357.             }
  358. #endif /* VERASE */
  359. #ifdef VEOF
  360.         } else if(cur_char == term_chars[VEOF] ){   /* ^D? */
  361.             if(max_pos == 0) {
  362.                 reset_termio();
  363.                 return((char *)NULL);
  364.             }
  365.             if((cur_pos < max_pos)&&(cur_char == 004)) { /* ^D */
  366.                 int i;
  367.                 for(i=cur_pos; i<max_pos; i++)
  368.                     cur_line[i] = cur_line[i+1];
  369.                 max_pos -= 1;
  370.                 fix_line();
  371.             }
  372. #endif /* VEOF */
  373. #ifdef VKILL
  374.         } else if(cur_char == term_chars[VKILL] ){  /* ^U? */
  375.             clear_line(prompt);
  376. #endif /* VKILL */
  377. #ifdef VWERASE
  378.         } else if(cur_char == term_chars[VWERASE] ){  /* ^W? */
  379.             while((cur_pos > 0) &&
  380.                   (cur_line[cur_pos-1] == SPACE)) {
  381.                 cur_pos -= 1;
  382.                 backspace();
  383.             }
  384.             while((cur_pos > 0) &&
  385.                   (cur_line[cur_pos-1] != SPACE)) {
  386.                 cur_pos -= 1;
  387.                 backspace();
  388.             }
  389.             clear_eoline();
  390.             max_pos = cur_pos;
  391. #endif /* VWERASE */
  392. #ifdef VREPRINT
  393.         } else if(cur_char == term_chars[VREPRINT] ){  /* ^R? */
  394.             putc('\n',stderr); /* go to a fresh line */
  395.             redraw_line(prompt);
  396. #endif /* VREPRINT */
  397. #ifdef VSUSP
  398.         } else if(cur_char == term_chars[VSUSP]) {
  399.             reset_termio();
  400.             kill(0, SIGTSTP);
  401.  
  402.             /* process stops here */
  403.  
  404.             set_termio();
  405.             /* print the prompt */
  406.             redraw_line(prompt);
  407. #endif /* VSUSP */
  408.         } else {
  409.             /* do normal editing commands */
  410.             /* some of these are also done above */
  411.             int i;
  412.             switch(cur_char) {
  413.                 case EOF:
  414.                 reset_termio();
  415.                 return((char *)NULL);
  416.                 case 001: /* ^A */
  417.                 while(cur_pos > 0) {
  418.                     cur_pos -= 1;
  419.                     backspace();
  420.                 }
  421.                 break;
  422.                 case 002: /* ^B */
  423.                 if(cur_pos > 0) {
  424.                     cur_pos -= 1;
  425.                     backspace();
  426.                 }
  427.                 break;
  428.                 case 005: /* ^E */
  429.                 while(cur_pos < max_pos) {
  430.                     user_putc(cur_line[cur_pos]);
  431.                     cur_pos += 1;
  432.                 }
  433.                 break;
  434.                 case 006: /* ^F */
  435.                 if(cur_pos < max_pos) {
  436.                     user_putc(cur_line[cur_pos]);
  437.                     cur_pos += 1;
  438.                 }
  439.                 break;
  440.                 case 013: /* ^K */
  441.                 clear_eoline();
  442.                 max_pos = cur_pos;
  443.                 break;
  444.                 case 020: /* ^P */
  445.                 if(history != NULL) {
  446.                     if(cur_entry == NULL) {
  447.                         cur_entry = history;
  448.                         clear_line(prompt);
  449.                         copy_line(cur_entry->line);
  450.                     } else if(cur_entry->prev != NULL) {
  451.                         cur_entry = cur_entry->prev;
  452.                         clear_line(prompt);
  453.                         copy_line(cur_entry->line);
  454.                     }
  455.                 }
  456.                 break;
  457.                 case 016: /* ^N */
  458.                 if(cur_entry != NULL) {
  459.                     cur_entry = cur_entry->next;
  460.                     clear_line(prompt);
  461.                     if(cur_entry != NULL) 
  462.                         copy_line(cur_entry->line);
  463.                     else
  464.                         cur_pos = max_pos = 0;
  465.                 }
  466.                 break;
  467.                 case 014: /* ^L */
  468.                 case 022: /* ^R */
  469.                 putc('\n',stderr); /* go to a fresh line */
  470.                 redraw_line(prompt);
  471.                 break;
  472.                 case 0177: /* DEL */
  473.                 case 010: /* ^H */
  474.                 if(cur_pos > 0) {
  475.                     cur_pos -= 1;
  476.                     backspace();
  477.                     for(i=cur_pos; i<max_pos; i++)
  478.                         cur_line[i] = cur_line[i+1];
  479.                     max_pos -= 1;
  480.                     fix_line();
  481.                 }
  482.                 break;
  483.                 case 004: /* ^D */
  484.                 if(max_pos == 0) {
  485.                     reset_termio();
  486.                     return((char *)NULL);
  487.                 }
  488.                 if(cur_pos < max_pos) {
  489.                     for(i=cur_pos; i<max_pos; i++)
  490.                         cur_line[i] = cur_line[i+1];
  491.                     max_pos -= 1;
  492.                     fix_line();
  493.                 }
  494.                 break;
  495.                 case 025:  /* ^U */
  496.                 clear_line(prompt);
  497.                 break;
  498.                 case 027:  /* ^W */
  499.                 while((cur_pos > 0) &&
  500.                       (cur_line[cur_pos-1] == SPACE)) {
  501.                     cur_pos -= 1;
  502.                     backspace();
  503.                 }
  504.                 while((cur_pos > 0) &&
  505.                       (cur_line[cur_pos-1] != SPACE)) {
  506.                     cur_pos -= 1;
  507.                     backspace();
  508.                 }
  509.                 clear_eoline();
  510.                 max_pos = cur_pos;
  511.                 break;
  512.                 case '\n': /* ^J */
  513.                 case '\r': /* ^M */
  514.                 cur_line[max_pos+1] = '\0';
  515.                 putc('\n', stderr);
  516.                 new_line = (char *)alloc((unsigned long) (strlen(cur_line)+1), "history");
  517.                 strcpy(new_line,cur_line);
  518.                 reset_termio();
  519.                 return(new_line);
  520.                 default:
  521.                 break;
  522.             }
  523.         }
  524.     }
  525. }
  526.  
  527. /* fix up the line from cur_pos to max_pos */
  528. /* do not need any terminal capabilities except backspace, */
  529. /* and space overwrites a character */
  530. static void
  531. fix_line()
  532. {
  533.     int i;
  534.  
  535.     /* write tail of string */
  536.     for(i=cur_pos; i<max_pos; i++)
  537.         user_putc(cur_line[i]);
  538.  
  539.     /* write a space at the end of the line in case we deleted one */
  540.     user_putc(SPACE);
  541.  
  542.     /* backup to original position */
  543.     for(i=max_pos+1; i>cur_pos; i--)
  544.         backspace();
  545.  
  546. }
  547.  
  548. /* redraw the entire line, putting the cursor where it belongs */
  549. static void
  550. redraw_line(prompt)
  551. char *prompt;
  552. {
  553.     int i;
  554.  
  555.     fputs(prompt, stderr);
  556.     user_puts(cur_line);
  557.  
  558.     /* put the cursor where it belongs */
  559.     for(i=max_pos; i>cur_pos; i--)
  560.         backspace();
  561. }
  562.  
  563. /* clear cur_line and the screen line */
  564. static void
  565. clear_line(prompt)
  566. char *prompt;
  567. {
  568.     int i;
  569.     for(i=0; i<max_pos; i++)
  570.         cur_line[i] = '\0';
  571.  
  572.     for(i=cur_pos; i>0; i--)
  573.         backspace();
  574.  
  575.     for(i=0; i<max_pos; i++)
  576.         putc(SPACE, stderr);
  577.  
  578.     putc('\r', stderr);
  579.     fputs(prompt, stderr);
  580.  
  581.     cur_pos = 0;
  582.     max_pos = 0;
  583. }
  584.  
  585. /* clear to end of line and the screen end of line */
  586. static void
  587. clear_eoline(prompt)
  588. char *prompt;
  589. {
  590.     int i;
  591.     for(i=cur_pos; i<max_pos; i++)
  592.         cur_line[i] = '\0';
  593.  
  594.     for(i=cur_pos; i<max_pos; i++)
  595.         putc(SPACE, stderr);
  596.     for(i=cur_pos; i<max_pos; i++)
  597.         backspace();
  598. }
  599.  
  600. /* copy line to cur_line, draw it and set cur_pos and max_pos */
  601. static void
  602. copy_line(line)
  603. char *line;
  604. {
  605.     strcpy(cur_line, line);
  606.     user_puts(cur_line);
  607.     cur_pos = max_pos = strlen(cur_line);
  608. }
  609.  
  610. /* add line to the history */
  611. void
  612. add_history(line)
  613. char *line;
  614. {
  615.     struct hist *entry;
  616.     entry = (struct hist *)alloc((unsigned long)sizeof(struct hist),"history");
  617.     entry->line = alloc((unsigned long)(strlen(line)+1),"history");
  618.     strcpy(entry->line, line);
  619.  
  620.     entry->prev = history;
  621.     entry->next = NULL;
  622.     if(history != NULL) {
  623.         history->next = entry;
  624.     }
  625.     history = entry;
  626. }
  627.  
  628.  
  629. /* Convert ANSI arrow keys to control characters */
  630. static char
  631. ansi_getc()
  632. {
  633.   char c = getc(stdin);
  634.   if (c == 033) {
  635.     c = getc(stdin); /* check for CSI */
  636.     if (c == '[') {
  637.       c = getc(stdin); /* get command character */
  638.       switch (c) {
  639.       case 'D': /* left arrow key */
  640.     c = 002;
  641.     break;
  642.       case 'C': /* right arrow key */
  643.     c = 006;
  644.     break;
  645.       case 'A': /* up arrow key */
  646.     c = 020;
  647.     break;
  648.       case 'B': /* down arrow key */
  649.     c = 016;
  650.     break;
  651.       }
  652.     }
  653.   }
  654.   return c;
  655. }
  656.  
  657. #if defined(MSDOS) || defined(_Windows) || defined(DOS386)
  658.  
  659. /* Convert Arrow keystrokes to Control characters: */
  660. static  char
  661. msdos_getch()
  662. {
  663. #ifdef DJGPP
  664.     char c;
  665.     int ch = getkey();
  666.     c = (ch & 0xff00) ? 0 : ch & 0xff;
  667. #else
  668.     char c = getch();
  669. #endif
  670.  
  671.     if (c == 0) {
  672. #ifdef DJGPP
  673.     c = ch & 0xff;
  674. #else
  675.     c = getch(); /* Get the extended code. */
  676. #endif
  677.     switch (c) {
  678.         case 75: /* Left Arrow. */
  679.         c = 002;
  680.         break;
  681.         case 77: /* Right Arrow. */
  682.         c = 006;
  683.         break;
  684.         case 72: /* Up Arrow. */
  685.         c = 020;
  686.         break;
  687.         case 80: /* Down Arrow. */
  688.         c = 016;
  689.         break;
  690.         case 115: /* Ctl Left Arrow. */
  691.         case 71: /* Home */
  692.         c = 001;
  693.         break;
  694.         case 116: /* Ctl Right Arrow. */
  695.         case 79: /* End */
  696.         c = 005;
  697.         break;
  698.         case 83: /* Delete */
  699.         c = 004;
  700.         break;
  701.         default:
  702.         c = 0;
  703.         break;
  704.     }
  705.     }
  706.     else if (c == 033) { /* ESC */
  707.     c = 025;
  708.     }
  709.  
  710.  
  711.     return c;
  712. }
  713.  
  714. #endif /* MSDOS */
  715.  
  716. #ifdef ATARI
  717.  
  718. /* Convert Arrow keystrokes to Control characters: TOS version */
  719.  
  720. /* the volatile could be necessary to keep gcc from reordering 
  721.    the two Super calls
  722. */
  723. #define CONTERM ((/*volatile*/ char *)0x484L)
  724.  
  725. static void 
  726. remove_conterm()
  727. {
  728.   void *ssp=(void*)Super(0L);
  729.   *CONTERM &= ~0x8;
  730.   Super(ssp);
  731. }
  732.  
  733. static    char
  734. tos_getch()
  735. {
  736.     long rawkey;
  737.     char c;
  738.     int scan_code;
  739.     void *ssp;
  740.     static  int init = 1;
  741.     static  int in_help = 0;
  742.  
  743.     if (in_help) {
  744.     switch(in_help) {
  745.         case 1:
  746.         case 5: in_help++; return 'e';
  747.         case 2:
  748.         case 6: in_help++; return 'l';
  749.         case 3:
  750.         case 7: in_help++; return 'p';
  751.         case 4: in_help = 0; return 0x0d;
  752.         case 8: in_help = 0; return ' ';
  753.     }
  754.     }
  755.  
  756.     if (init) {
  757.     ssp = (void*)Super(0L);
  758.     if( !(*CONTERM & 0x8) ) {
  759.         *CONTERM |= 0x8;
  760.     } else {
  761.         init=0;
  762.     }
  763.     (void)Super(ssp);
  764.     if( init ) {
  765.         atexit(remove_conterm);
  766.         init = 0;
  767.     }
  768.     }
  769.  
  770.    (void)Cursconf(1, 0); /* cursor on */
  771.     rawkey = Cnecin();
  772.     c = (char)rawkey;
  773.     scan_code= ((int)(rawkey>>16)) & 0xff;    /* get the scancode */
  774.     if( rawkey&0x07000000 ) scan_code |= 0x80;     /* shift or control */
  775.  
  776.     switch (scan_code) {
  777.     case 0x62:                /* HELP        */
  778.         if (max_pos==0) {
  779.         in_help = 1;
  780.         return 'h';
  781.         } else {
  782.         return 0;
  783.         }
  784.     case 0xe2:                /* shift HELP    */
  785.         if (max_pos==0) {
  786.         in_help = 5;
  787.         return 'h';
  788.         } else {
  789.         return 0;
  790.         }
  791.     case 0x48: /* Up Arrow */
  792.         return 0x10; /* ^P */
  793.     case 0x50: /* Down Arrow */
  794.         return 0x0e; /* ^N */
  795.     case 0x4b: /* Left Arrow */
  796.         return 0x02; /* ^B */
  797.     case 0x4d: /* Right Arrow */
  798.         return 0x06; /* ^F */
  799.     case 0xcb: /* Shift Left Arrow */
  800.     case 0xf3: /* Ctrl Left Arrow (TOS-bug ?) */
  801.     case 0x47: /* Home */
  802.         return 0x01; /* ^A */
  803.     case 0xcd: /* Shift Right Arrow */
  804.     case 0xf4: /* Ctrl Right Arrow (TOS-bug ?) */
  805.     case 0xc7: /* Shift Home */
  806.     case 0xf7: /* Crtl Home */
  807.         return 0x05; /* ^E */
  808.     case 0x61: /* Undo - redraw line */
  809.         return 0x0c; /* ^L */
  810.     default:
  811.         if (c == 0x1b) return 0x15; /* ESC becomes ^U */
  812.         if (c == 0x7f) return 0x04; /* Del becomes ^D */
  813.         break;
  814.     }
  815.  
  816.     return c;
  817. }
  818.  
  819. #endif /* ATARI */
  820.  
  821.   /* set termio so we can do our own input processing */
  822. static void
  823. set_termio()
  824. {
  825. #if !defined(MSDOS) && !defined(ATARI) && !defined(_Windows) && !defined(DOS386)
  826. /* set termio so we can do our own input processing */
  827. /* and save the old terminal modes so we can reset them later */
  828.     if(term_set == 0) {
  829.         /*
  830.          * Get terminal modes.
  831.          */
  832. #ifdef SGTTY
  833.         ioctl(0, TIOCGETP, &orig_termio);
  834. #else  /* SGTTY */
  835. #ifdef TERMIOS
  836. #ifdef TCGETS
  837.         ioctl(0, TCGETS, &orig_termio);
  838. #else
  839.         tcgetattr(0, &orig_termio);
  840. #endif /* TCGETS */
  841. #else
  842.         ioctl(0, TCGETA, &orig_termio);
  843. #endif /* TERMIOS */
  844. #endif /* SGTTY */
  845.  
  846.         /*
  847.          * Save terminal modes
  848.          */
  849.         rl_termio = orig_termio;
  850.  
  851.         /*
  852.          * Set the modes to the way we want them
  853.          *  and save our input special characters
  854.          */
  855. #ifdef SGTTY
  856.         rl_termio.sg_flags |= CBREAK;
  857.         rl_termio.sg_flags &= ~(ECHO|XTABS);
  858.         ioctl(0, TIOCSETN, &rl_termio);
  859.  
  860.         ioctl(0, TIOCGETC, &s_tchars);
  861.         term_chars[VERASE]   = orig_termio.sg_erase;
  862.         term_chars[VEOF]     = s_tchars.t_eofc;
  863.         term_chars[VKILL]    = orig_termio.sg_kill;
  864. #ifdef TIOCGLTC
  865.         ioctl(0, TIOCGLTC, &s_ltchars);
  866.         term_chars[VWERASE]  = s_ltchars.t_werasc;
  867.         term_chars[VREPRINT] = s_ltchars.t_rprntc;
  868.         term_chars[VSUSP]    = s_ltchars.t_suspc;
  869.  
  870.         /* disable suspending process on ^Z */
  871.         s_ltchars.t_suspc = 0;
  872.         ioctl(0, TIOCSLTC, &s_ltchars);
  873. #endif /* TIOCGLTC */
  874. #else  /* SGTTY */
  875.         rl_termio.c_iflag &= ~(BRKINT|PARMRK|INPCK|IUCLC|IXON|IXOFF);
  876.         rl_termio.c_iflag |=  (IGNBRK|IGNPAR);
  877.  
  878.         /* rl_termio.c_oflag &= ~(ONOCR); Costas Sphocleous Irvine,CA */
  879.  
  880.         rl_termio.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|NOFLSH);
  881. #ifdef OS2
  882.  /* for emx: remove default terminal processing */
  883.                 rl_termio.c_lflag &= ~(IDEFAULT);
  884. #endif /* OS2 */
  885.         rl_termio.c_lflag |=  (ISIG);
  886.         rl_termio.c_cc[VMIN] = 1;
  887.         rl_termio.c_cc[VTIME] = 0;
  888.  
  889. #ifndef VWERASE
  890. #define VWERASE 3
  891. #endif
  892.         term_chars[VERASE]   = orig_termio.c_cc[VERASE];
  893.         term_chars[VEOF]     = orig_termio.c_cc[VEOF];
  894.         term_chars[VKILL]    = orig_termio.c_cc[VKILL];
  895. #ifdef TERMIOS
  896.         term_chars[VWERASE]  = orig_termio.c_cc[VWERASE];
  897. #ifdef VREPRINT
  898.         term_chars[VREPRINT] = orig_termio.c_cc[VREPRINT];
  899. #else
  900. #ifdef VRPRNT
  901.         term_chars[VRPRNT] = orig_termio.c_cc[VRPRNT];
  902. #endif
  903. #endif
  904.         term_chars[VSUSP]    = orig_termio.c_cc[VSUSP];
  905.  
  906.         /* disable suspending process on ^Z */
  907.         rl_termio.c_cc[VSUSP] = 0;
  908. #endif /* TERMIOS */
  909. #endif /* SGTTY */
  910.  
  911.         /*
  912.          * Set the new terminal modes.
  913.          */
  914. #ifdef SGTTY
  915.         ioctl(0, TIOCSLTC, &s_ltchars);
  916. #else
  917. #ifdef TERMIOS
  918. #ifdef TCSETSW
  919.         ioctl(0, TCSETSW, &rl_termio);
  920. #else
  921.         tcsetattr(0, TCSADRAIN, &rl_termio);
  922. #endif /* TCSETSW */
  923. #else
  924.         ioctl(0, TCSETAW, &rl_termio);
  925. #endif /* TERMIOS */
  926. #endif /* SGTTY */
  927.         term_set = 1;
  928.     }
  929. #endif /* !MSDOS && !ATARI && !defined(_Windows) */
  930. }
  931.   
  932. static void
  933. reset_termio()
  934. {
  935. #if !defined(MSDOS) && !defined(ATARI) && !defined(_Windows) && !defined(DOS386)
  936. /* reset saved terminal modes */
  937.     if(term_set == 1) {
  938. #ifdef SGTTY
  939.         ioctl(0, TIOCSETN, &orig_termio);
  940. #ifdef TIOCGLTC
  941.         /* enable suspending process on ^Z */
  942.         s_ltchars.t_suspc = term_chars[VSUSP];
  943.         ioctl(0, TIOCSLTC, &s_ltchars);
  944. #endif /* TIOCGLTC */
  945. #else  /* SGTTY */
  946. #ifdef TERMIOS
  947. #ifdef TCSETSW
  948.         ioctl(0, TCSETSW, &orig_termio);
  949. #else
  950.         tcsetattr(0, TCSADRAIN, &orig_termio);
  951. #endif /* TCSETSW */
  952. #else
  953.         ioctl(0, TCSETAW, &orig_termio);
  954. #endif /* TERMIOS */
  955. #endif /* SGTTY */
  956.         term_set = 0;
  957.     }
  958. #endif /* !MSDOS && !ATARI && !_Windows */
  959. }
  960. #endif /* READLINE */
  961.